package com.maserb.monitor.service.schoolStudent.impl;

import com.maserb.monitor.entity.JwOrgEntity;
import com.maserb.monitor.entity.SysCode;
import com.maserb.monitor.entity.UserEntity;
import com.maserb.monitor.entity.schoolStudent.SchoolStudentEntity;
import com.maserb.monitor.entity.schoolStudent.StudentAchieveEntity;
import com.maserb.monitor.entity.schoolStudent.StudentScoreEntity;
import com.maserb.monitor.repository.schoolStudent.SchoolTimeTableRepository;
import com.maserb.monitor.repository.schoolStudent.StudentScoreRepository;
import com.maserb.monitor.service.author_manage.UserService;
import com.maserb.monitor.service.base.impl.JpaSpecificationServiceImpl;
import com.maserb.monitor.service.jwEducation.JwOrgService;
import com.maserb.monitor.service.schoolStudent.StudentAchieveService;
import com.maserb.monitor.service.schoolStudent.StudentScoreService;
import com.maserb.monitor.service.sysCode.SysCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.thymeleaf.util.StringUtils;

import javax.persistence.criteria.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class StudentScoreServiceImpl extends JpaSpecificationServiceImpl<StudentScoreRepository,
        StudentScoreRepository, StudentScoreEntity, String>
        implements StudentScoreService {

    @Autowired
    private SchoolTimeTableRepository schoolTimeTableRepository;

    @Autowired
    SysCodeService codeService;

    @Autowired
    JwOrgService orgService;

    @Autowired
    StudentAchieveService achieveService;

    @Autowired
    UserService userService;

    @Override
    public List<StudentScoreEntity> findByAchieve(StudentAchieveEntity achieve) {
        return this.repository.findByAchieve(achieve);
    }

    @Override
    public List<StudentScoreEntity> findByAchieveOrderByScoreDesc(StudentAchieveEntity achieve) {
        return this.repository.findByAchieveOrderByScoreDesc(achieve);
    }

    @Override
    public Page<StudentScoreEntity> findAllByAchieveId(HttpServletRequest request,String achieveId, Pageable pageable) {
        HttpSession session = request.getSession(true);
        UserEntity user = (UserEntity) session.getAttribute("user");
        SysCode code = new SysCode();
        StudentAchieveEntity achieveEntity = new StudentAchieveEntity();
        if(null!=user && !StringUtils.isEmptyOrWhitespace(user.getSysCodeId())){
            code = codeService.findOne(user.getSysCodeId());
        }
        if(!StringUtils.isEmptyOrWhitespace(achieveId)){
            achieveEntity = achieveService.findOne(achieveId);
        }else{
            return  null;
        }
        return this.findAll(getSpecification(achieveEntity,code),pageable);
    }



    private Specification<StudentScoreEntity> getSpecification(StudentAchieveEntity achieveEntity,SysCode sysCode){
        return new Specification<StudentScoreEntity>() {
            @Override
            public Predicate toPredicate(Root<StudentScoreEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {

                Path<StudentAchieveEntity> pathAchieve= root.get("achieve");
                Path<SysCode> pathSubject = root.join("subject");

                ArrayList<Predicate> list = new ArrayList<Predicate>();
                if(null!=achieveEntity&&!StringUtils.isEmptyOrWhitespace(achieveEntity.getId())){
                    list.add(criteriaBuilder.and(criteriaBuilder.equal(pathAchieve, achieveEntity)));
                }
                if(null!=sysCode&&!StringUtils.isEmptyOrWhitespace(sysCode.getId())){
                    list.add(criteriaBuilder.and(criteriaBuilder.equal(pathSubject, sysCode)));
                }
                return criteriaBuilder.and(list.toArray(new Predicate[list.size()]));
            }
        };
    }

    @Override
    public void save(StudentScoreEntity entity, String parentId) {
        StudentAchieveEntity achieveEntity = achieveService.findOne(parentId);
        entity.setAchieve(achieveEntity);
        repository.save(entity);
    }

    /**
     * 更新成绩信息
     * @param parentId
     */
    @Override
    public void updateAchieve(String parentId) {
        StudentAchieveEntity achieveEntity = achieveService.findOne(parentId);
        List<StudentScoreEntity>scoreEntities = this.repository.findByAchieve(achieveEntity);
        if(scoreEntities.size()>0){
            Double totalScore = 0d;
            Double avgScore = 0d;
            Integer subjectCount = scoreEntities.size();
            for(StudentScoreEntity scoreEntity : scoreEntities){
                totalScore += scoreEntity.getScore();
            }
            avgScore = (double)Math.round((totalScore/subjectCount)*10)/10;
            achieveEntity.setTotalScore(totalScore);
            achieveEntity.setAvgScore(avgScore);
            achieveEntity.setSubjectCount(subjectCount);
            achieveService.save(achieveEntity);
        }
    }

    @Override
    public void delete(String var1) {
        StudentScoreEntity scoreEntity = this.findOne(var1);
        StudentAchieveEntity achieveEntity = scoreEntity.getAchieve();
        super.delete(var1);
        updateAchieve(achieveEntity.getId());
    }

    private Specification<StudentScoreEntity>getSpecificationByUser(List<String> orgIdList,String userId, String name,String studentId, final String term, final String clazzId,SysCode sysCode){
        return new Specification<StudentScoreEntity>() {
            @Override
            public Predicate toPredicate(Root<StudentScoreEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                ArrayList<Predicate> list = new ArrayList<Predicate>();
                Join<StudentScoreEntity, StudentAchieveEntity> joinAchieve = root.join("achieve", JoinType.LEFT);
                Join<StudentAchieveEntity, SchoolStudentEntity> joinStudent = joinAchieve.join("student", JoinType.LEFT);
                Path<String> pathJoinStudent = joinStudent.get("id");
                Path<String> pathJoinStudentName = joinStudent.get("name");
                Path<String> pathJoinStudentId = joinStudent.get("studentId");
                Path<String> pathJoinStudentOrgId = joinStudent.get("orgId");
                list.add(criteriaBuilder.and(criteriaBuilder.equal(pathJoinStudent, joinAchieve.get("student"))));
                Path<String> pathTerm = joinAchieve.get("term");
                Path<Date> pathCreateTime = joinAchieve.get("createTime");
                Path<SysCode> pathSubject = root.join("subject");
                if (null!=orgIdList && orgIdList.size()>0) {
                    Expression<String> exp = pathJoinStudentOrgId;
                    list.add(exp.in(orgIdList));
                }
                if (!StringUtils.isEmptyOrWhitespace(name)) {
                    list.add(criteriaBuilder.and(criteriaBuilder.like(pathJoinStudentName, "%"+name+"%")));
                }
                if (!StringUtils.isEmptyOrWhitespace(clazzId)) {
                    list.add(criteriaBuilder.and(criteriaBuilder.equal(pathJoinStudentOrgId, clazzId)));
                }
                if (!StringUtils.isEmptyOrWhitespace(studentId)) {
                    list.add(criteriaBuilder.and(criteriaBuilder.equal(pathJoinStudentId, studentId)));
                }
                if (!StringUtils.isEmptyOrWhitespace(term)) {
                    list.add(criteriaBuilder.and(criteriaBuilder.like(pathTerm, "%"+term+"%")));
                }
                if(null!=sysCode&&!StringUtils.isEmptyOrWhitespace(sysCode.getId())){
                    list.add(criteriaBuilder.and(criteriaBuilder.equal(pathSubject, sysCode)));
                }
                return criteriaBuilder.and(list.toArray(new Predicate[list.size()]));
            }
        };
    }

    @Override
    public Page<StudentScoreEntity> findAllByUser(Pageable var1,String userId, String name,String studentId,String term,String clazzId) {
        UserEntity user = new UserEntity();
        List<JwOrgEntity> orgList = new ArrayList<JwOrgEntity>();
        List<String>orgIdList = new ArrayList<String>();
        SysCode code = new SysCode();
        if(!StringUtils.isEmptyOrWhitespace(userId)){
            user = userService.findOne(userId);
            if(null!=user && !StringUtils.isEmptyOrWhitespace(user.getSysCodeId())){
                code = codeService.findOne(user.getSysCodeId());
            }
            if(null!=user &&!"".equals( user.getId())){
                orgList = orgService.findByUser(user);
                if(orgList.size()>0){
                    for(JwOrgEntity org:orgList){
                        orgIdList.add(org.getId());
                    }
                }else{
                    String orgId = user.getOrgId();
                    JwOrgEntity orgEntity = orgService.findOne(orgId);
                    if(null!=orgEntity && orgEntity.getTreeLevel()<1){

                    }else{
                        return null;
                    }
                }
            }
        }
        return this.findAll(getSpecificationByUser(orgIdList,userId,name,studentId,term,clazzId,code),var1);
    }

}